#include "stdafx.h"
#include "dispTestObjectList.h"
#include "dispIdManager.h"
#include "java.h"
#include "jtf.h"
#include "jniReference.h"
#include "customException.h"
#include <sstream>

void CDispTestObjectList::InitializeList()
{
  if (!mjobjElements)
    return;
  mElements.clear();
  JavaListClass javaList;
  if (!javaList.IsInstance(mjobjElements))
    return;

  int iListSize = javaList.Size.Invoke(mjobjElements);
  for (int i = 0; i < iListSize; ++i)
  {
    CJniLocalReference<jobject> jobjListEntry =  javaList.Get.Invoke(mjobjElements, i);
    CComVariant varElement;
    mJavaReflection.JobjectToVariant(jobjListEntry.Detach(), &varElement); // CHECK
    mElements.push_back(varElement);
  }
}

BSTR CDispTestObjectList::ToString()
{
  std::wstringstream tmp;
  tmp << L"{";
  for (std::vector<CComVariant>::iterator it = mElements.begin(); it != mElements.end(); ++it)
  {
    if (tmp.str().length() > 1)
      tmp << ", ";
    switch(it->vt)
    {
    case VT_DISPATCH:
      {
        CComVariant vValue;
        it->pdispVal->Invoke(0, IID_IDispatch, 0, 0, 0, &vValue, 0, 0);
        tmp << vValue.bstrVal;
        continue;
      }
    case VT_BSTR:
      {
        tmp << it->bstrVal;
        continue;
      }
    case VT_I4: 
    case VT_INT:
      {
        tmp << it->intVal;
        continue;
      }
    case VT_BOOL:
      {
        tmp << it->boolVal;
        continue;
      }
    default:
      tmp << L"<unknown type>";
    }
  }
  tmp << L"}";
  return SysAllocString(tmp.str().c_str());
}

HRESULT CDispTestObjectList::InvokeDynamicMethod(const std::wstring& strDispName, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr)
{
  if (::_wcsicmp(strDispName.c_str(), L"get") == 0)
  {
    if (pdispparams->cArgs == 1 && (pdispparams->rgvarg[0].vt == VT_INT || pdispparams->rgvarg[0].vt == VT_I4))
    {
      if (pdispparams->rgvarg[0].intVal >= 0 && pdispparams->rgvarg[0].intVal < mElements.size())
      {
        CComVariant tmp = mElements[pdispparams->rgvarg[0].intVal];
        tmp.Detach(pvarResult);
        return S_OK;
      }
      else
      {
        throw CustomException(1000, L"Dispatch List", L"Index out of range.");
      }
    }
    else
    {
      throw CustomException(1000, L"Dispatch List", L"Invalid argument.");
    }
  }
  throw CustomException(1000, L"Dispatch List", L"Method not supported.");
  return E_FAIL;
}

HRESULT CDispTestObjectList::GetDynamicProperty(const std::wstring& strDispName, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr)
{
  if (::_wcsicmp(strDispName.c_str(), L"size") == 0 || ::_wcsicmp(strDispName.c_str(), L"length") == 0)
  {
    pvarResult->vt = VT_INT;
    pvarResult->intVal = mElements.size();
    return S_OK;
  }
  else
  {
    int i = _wtoi(strDispName.c_str());
    // if the property name is a number, return the corresponding element
    if (i || strDispName.c_str()[0] == L'0')
    {
      if (i >= 0 && i < mElements.size())
      {
        CComVariant tmp = mElements[i];
        tmp.Detach(pvarResult);
        return S_OK;
      }
      else
      {
        throw CustomException(1000, L"Dispatch List", L"Index out of range.");
      }
    }
  }
  throw CustomException(1000, L"Dispatch List", L"Property not supported.");
  return E_FAIL;
}

HRESULT CDispTestObjectList::SetDynamicProperty(const std::wstring& strDispName, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr)
{
  throw CustomException(1000, L"Dispatch List", L"Property not supported.");
  return E_FAIL;
}